﻿namespace Tszy.Unlimited.Base.Infrastructure.Domain;

/// <summary>
/// 领域根。
/// </summary>
public abstract class AggregateRoot : IAggregateRoot
{
    /// <summary>
    /// 领域事件集合。
    /// </summary>
    private readonly List<IDomainEvent> _domainEvents = new();

    /// <summary>
    /// 初始化。
    /// </summary>
    protected AggregateRoot()
    {
    }

    /// <summary>
    /// 领域事件集合。
    /// </summary>
    public virtual IReadOnlyCollection<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();

    /// <summary>
    /// 应用领域事件。
    /// </summary>
    /// <param name="domainEvent">领域事件。</param>
    /// <returns>领域模型。</returns>
    public virtual IAggregateRoot ApplyEvent(IDomainEvent domainEvent)
    {
        RaiseDomainEvent(domainEvent);
        return this;
    }

    /// <summary>
    /// 清除所有事件修改信息。
    /// </summary>
    public virtual void ClearEvents()
    {
        _domainEvents.Clear();
    }

    /// <summary>
    /// 引发事件。
    /// </summary>
    /// <param name="domainEvent"></param>
    protected virtual void RaiseDomainEvent(IDomainEvent domainEvent)
    {
        _domainEvents.Add(domainEvent);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <returns></returns>
    public static bool operator ==(AggregateRoot? left, AggregateRoot? right)
    {
        bool flag = left is null;
        bool flag2 = right is null;

        // 2 个都是 null 时，返回 True。
        if (flag2 && flag)
            return true;

        // 其中一个是 null，另一个不是 null 时，返回 false。
        if (flag2 || flag)
            return false;

        return left!.GetHashCode() == right!.GetHashCode();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <returns></returns>
    public static bool operator !=(AggregateRoot? left, AggregateRoot? right)
    {
        return !(left == right);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exists"></param>
    public static implicit operator bool(AggregateRoot exists)
    {
        return exists != null;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override int GetHashCode() => base.GetHashCode();

    /// <summary>
    /// 
    /// </summary>
    /// <param name="other"></param>
    /// <returns></returns>
    public override bool Equals(object? other) => this == other as AggregateRoot;
}

/// <summary>
/// 领域根。
/// </summary>
/// <typeparam name="TIdentity"></typeparam>
public abstract class AggregateRoot<TIdentity> : AggregateRoot
{
    /// <summary>
    /// 初始化。
    /// </summary>
    protected AggregateRoot() : this(default, DateTime.Now)
    {
    }

    /// <summary>
    /// 初始化。
    /// </summary>
    protected AggregateRoot(TIdentity? identity, DateTime created)
    {
        Identity = identity;
        Created = created;
    }

    /// <summary>
    /// 唯一标识。
    /// </summary>
    public virtual TIdentity? Identity { get; protected set; }

    /// <summary>
    /// 创建时间。
    /// </summary>
    public virtual DateTime Created { get; protected set; } = DateTime.Now;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <returns></returns>
    public static bool operator ==(AggregateRoot<TIdentity>? left, AggregateRoot<TIdentity>? right)
    {
        bool flag = left is null;
        bool flag2 = right is null;

        // 2 个都是 null 时，返回 True。
        if (flag2 && flag)
            return true;

        // 其中一个是 null，另一个不是 null 时，返回 false。
        if (flag2 || flag)
            return false;

        flag = left!.Identity == null;
        flag2 = right!.Identity == null;

        // 2 个都是 null 时，返回 True。
        if (flag2 && flag)
            return true;

        // 其中一个是 null，另一个不是 null 时，返回 false。
        if (flag2 || flag)
            return false;

        if (left!.Identity!.Equals(right!.Identity))
            return true;

        return left!.GetHashCode() == right!.GetHashCode();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <returns></returns>
    public static bool operator !=(AggregateRoot<TIdentity>? left, AggregateRoot<TIdentity>? right)
    {
        return !(left == right);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="exists"></param>
    public static implicit operator bool(AggregateRoot<TIdentity> exists)
    {
        return exists != null;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override int GetHashCode() => base.GetHashCode();

    /// <summary>
    /// 
    /// </summary>
    /// <param name="other"></param>
    /// <returns></returns>
    public override bool Equals(object? other) => this == other as AggregateRoot<TIdentity>;
}